import dayjs from 'dayjs';
import type Modeler from 'bpmn-js/lib/Modeler';
import modelerStore from '@/store/modules/modeler';
import type { Element } from 'diagram-js/lib/model/Types';
import { connectionAttr } from '@/store/modules/connectionAttr';
import { is } from 'bpmn-js/lib/util/ModelUtil';

interface FlowElement {
  id: string;
  type: string;
  name?: string;
  businessObject: any;
  incoming?: FlowElement[];
  outgoing?: [];
}
/**
 * @description 处理首字母大写 abc => Abc
 * @param str
 */
export const changeStr = (str: string) => {
  return str.charAt(0).toUpperCase() + str.slice(1);
};

/**
 * @description 随机生成颜色
 * @param {string} type
 * @return {string}
 */
export const randomColor = (type: 'rgb' | 'hex' | 'hsl'): string => {
  switch (type) {
    case 'rgb':
      return window.crypto.getRandomValues(new Uint8Array(3)).toString();
    case 'hex':
      return `#${Math.floor(Math.random() * 0xffffff)
        .toString(16)
        .padStart(6, `${Math.random() * 10}`)}`;
    case 'hsl':
      // 在25-95%范围内具有饱和度，在85-95%范围内具有亮度
      return [360 * Math.random(), `${100 * Math.random()}%`, `${100 * Math.random()}%`].toString();
  }
};

/**
 * 复制文本
 * @param text
 */
export const copyText = (text: string) => {
  return new Promise((resolve) => {
    const copyInput = document.createElement('input'); //创建一个input框获取需要复制的文本内容
    copyInput.value = text;
    document.body.appendChild(copyInput);
    copyInput.select();
    document.execCommand('copy');
    copyInput.remove();
    resolve(true);
  });
};

/**
 * @description 判断字符串是否是base64
 * @param {string} str
 */
export const isBase64 = (str: string): boolean => {
  if (str === '' || str.trim() === '') {
    return false;
  }
  try {
    return btoa(atob(str)) == str;
  } catch (err) {
    return false;
  }
};
// 对象转JSON
export const toJSON = (obj) => {
  return JSON.stringify(obj, (_, value) => {
    switch (true) {
      case typeof value === 'undefined':
        return 'undefined';
      case typeof value === 'symbol':
        return value.toString();
      case typeof value === 'function':
        return value.toString();
      default:
        break;
    }
    return value;
  });
};

/***
 * @description 是否是生产环境
 */
export const IS_PROD = import.meta.env.PROD;
export const IS_DEV = import.meta.env.DEV;

/***
 * @description 格式化日期
 * @param time
 */
export const formatDate = (time) => dayjs(time).format('YYYY-MM-DD HH:mm:ss');

/**
 *  @description 将一维数组转成树形结构数据
 * @param items
 * @param id
 * @param link
 */
export const generateTree = (items, id = 0, link = 'parent') => {
  return items
    .filter((item) => item[link] == id)
    .map((item) => ({
      ...item,
      slots: { title: 'name' },
      children: generateTree(items, item.departmentid),
    }));
};
/**
 * 
 * @param data 自定义树形结构数据
 * @param id 
 * @param parentId 
 * @param children 
 * @returns 
 */
export function handleTree(data, id, parentId, children) {
  let config = {
    id: id || 'id',
    parentId: parentId || 'parentId',
    childrenList: children || 'children'
  };

  var childrenListMap = {};
  var nodeIds = {};
  var tree = [];

  for (let d of data) {
    let parentId = d[config.parentId];
    if (childrenListMap[parentId] == null) {
      childrenListMap[parentId] = [];
    }
    nodeIds[d[config.id]] = d;
    childrenListMap[parentId].push(d);
  }

  for (let d of data) {
    let parentId = d[config.parentId];
    if (nodeIds[parentId] == null) {
      tree.push(d);
    }
  }

  for (let t of tree) {
    adaptToChildrenList(t);
  }

  function adaptToChildrenList(o) {
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]];
    }
    if (o[config.childrenList]) {
      for (let c of o[config.childrenList]) {
        adaptToChildrenList(c);
      }
    }
  }
  return tree;
}

/***
 * @description 原生加密明文
 * @param {string} plaintext
 */
// const encryption = (plaintext: string) =>
//   isBase64(plaintext) ? plaintext : window.btoa(window.encodeURIComponent(plaintext));

/**
 * @description 原生解密
 * @param {string} ciphertext
 */
// const decryption = (ciphertext: string) =>
//   isBase64(ciphertext) ? window.decodeURIComponent(window.atob(ciphertext)) : ciphertext;

// const viewsModules = import.meta.glob('../views/**/*.vue');

// /**
//  *
//  * @param {string} viewPath 页面的路径 `@/view/${viewPath}`
//  * @param {string} viewFileName  页面文件 默认 index.vue
//  */
// export const getAsyncPage = (viewPath: string, viewFileName = 'index') => {
//   if (viewPath.endsWith('.vue')) {
//     const p = `../views/${viewPath}`;
//     const pathKey = Object.keys(viewsModules).find((key) => key === p)!;
//     // console.log('viewsModules[pathKey]', viewsModules[pathKey]);
//     return viewsModules[pathKey];
//   } else {
//     const p = `../views/${viewPath}/${viewFileName}.vue`;
//     const pathKey = Object.keys(viewsModules).find((key) => key === p)!;
//     // console.log('viewsModules[pathKey]', viewsModules[pathKey]);
//     return viewsModules[pathKey];
//     // return () => import(/* @vite-ignore */ `../views/${viewPath}/${viewFileName}.vue`);
//   }
// };

/**
 * / _ - 转换成驼峰并将view替换成空字符串
 * @param {*} name name
 */
export const toHump = (name) => {
  return name
    .replace(/[-/_](\w)/g, (_, letter) => {
      return letter.toUpperCase();
    })
    .replace('views', '');
};

/** 模拟异步请求，实用性不高，主要用于demo模拟请求 */
export const waitTime = <T>(time = 100, data: any = true): Promise<T> => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(data);
    }, time);
  });
};
export function tansParams(params) {
  let result = '';
  for (const propName of Object.keys(params)) {
    const value = params[propName];
    const part = `${encodeURIComponent(propName)}=`;
    if (value !== null && typeof value !== 'undefined') {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
            const params = `${propName}[${key}]`;
            const subPart = `${encodeURIComponent(params)}=`;
            result += `${subPart + encodeURIComponent(value[key])}&`;
          }
        }
      } else {
        result += `${part + encodeURIComponent(value)}&`;
      }
    }
  }
  return result;
}
/**
 * 获取表单字段List
 * @param json
 * @returns {*[]}
 */
export function getFormDataJson(json){
  let dataJson=[];
  let key={
    id:'',
    label:'',
    value:'',
    compType:'',
    options:[],
    dataType:'',
    action:'',
    isEdit:false,
    isDisabled:false,
    isMustInput:false
  };
  json.forEach(item => {
    if (['text','divider','barCode','alert','link','button','upload','dynamicTable','colorPicker'].includes(item.compType)) {
      return;
    }
    else if (item.compType == 'row'){
      item.columns.forEach(row => {
        row.list.forEach(list => {
          if (['text','divider','barCode','alert','link','button','upload','dynamicTable','colorPicker'].includes(list.compType)) {
            return;
          }
          else if (['select','radio','cascader','checkbox'].includes(list.compType)){
            key={
              id:'',
              label:'',
              value:'',
              compType:'',
              options:[],
              dataType:'',
              action:'',
              isEdit:false,
              isDisabled:false,
              isMustInput:false
            };
            key.id=list.id;
            key.value=list.id;
            key.label=list.label;
            key.compType=list.compType;
            key.options=list.options;
            key.dataType='string';
            key.action=list.action;
            dataJson.push(key);
          }
          else{
            key={
              id:'',
              label:'',
              value:'',
              compType:'',
              options:[],
              dataType:'',
              action:'',
              isEdit:false,
              isDisabled:false,
              isMustInput:false
            };
            if(['input','dialogList','date','time','Switch'].includes(list.compType)){
              key.dataType='string';
            }
            if(['rate','slider','inputNumber'].includes(list.compType)){
              key.dataType='int';
            }
            if(['textarea','editor','upload'].includes(list.compType)){
              key.dataType='text';
            }
            key.id=list.id;
            key.value=list.id;
            key.label=list.label;
            key.compType=list.compType;
            dataJson.push(key);
          }
        });
      });
    }else if (['select','radio','cascader','checkbox'].includes(item.compType)){
      key={
        id:'',
        label:'',
        value:'',
        compType:'',
        options:[],
        dataType:'string',
        action:'',
        isEdit:false,
        isDisabled:false,
        isMustInput:false
      };
      key.id=item.id;
      key.value=item.id;
      key.label=item.label;
      key.compType=item.compType;
      key.options=item.options;
      key.action=item.action;
      dataJson.push(key);
    }
    else{
      key={
        id:'',
        label:'',
        value:'',
        compType:'',
        options:[],
        dataType:'',
        action:'',
        isEdit:false,
        isDisabled:false,
        isMustInput:false
      };
      if(['input','dialogList','date','time','Switch'].includes(item.compType)){
        key.dataType='string';
      }
      if(['rate','slider','inputNumber'].includes(item.compType)){
        key.dataType='int';
      }
      if(['textarea','editor','upload'].includes(item.compType)){
        key.dataType='text';
      }
      key.id=item.id;
      key.value=item.id;
      key.label=item.label;
      key.compType=item.compType;
      dataJson.push(key);
    }
  })
  return dataJson;
}
export function itemReadOnly(json,dataPower){
  let newRefList = json.filter((item) => {
    if (['text','divider','barCode','alert','link','button','colorPicker'].includes(item.compType)) {
      return item;
    } else if (item.compType == 'dynamicTable') {
      let childrenColumns = item.columns.filter((col) => {
        if (col.compType == 'text') {
          return col;
        } else {
          if(dataPower!==undefined&&dataPower.length>0){
            const attr=dataPower.filter((dataItem)=>dataItem.id==col.id);
            col.readonly = attr[0].isEdit==true?false:true;
            col.disabled = attr[0].isEdit==true?false:true;
            col.isShow = attr[0].isDisabled;
            col.required =attr[0].isMustInput;
            col.rules = [];
          }
          else{
            col.readonly = true;
            col.disabled = true;
            col.required =true;
            col.rules = [];
          }
          return col;
        }
      });
      item.buttonAdd = false;
      item.buttonDel = false;
      item.showBatchBtn = false;
      return (item.columns = childrenColumns);
    } else if (item.compType == 'row') {
      let rows = item.columns;
      let colRows = rows.filter((row) => {
        let rowList = row.list;
        let colRowList = rowList.filter((rl) => {
          if (['text','divider','barCode','alert','link','button','colorPicker'].includes(rl.compType)) {
            return rl;
          } else if (rl.compType == 'dynamicTable') {
            let childrenColumns = rl.columns.filter((col) => {
              if (col.compType == 'text') {
                return col;
              }  else {
                if(dataPower!==undefined&&dataPower.length>0){
                  const attr=dataPower.filter((dataItem)=>dataItem.id==col.id);
                  col.readonly = attr[0].isEdit==true?false:true;
                  col.disabled = attr[0].isEdit==true?false:true;
                  col.isShow = attr[0].isDisabled;
                  col.required =attr[0].isMustInput;
                  col.rules = [];
                }
                else{
                  col.readonly = true;
                  col.disabled = true;
                  col.required =true;
                  col.rules = [];
                }
                return col;
              }
            });
            rl.buttonAdd = false;
            rl.buttonDel = false;
            rl.showBatchBtn = false;
            return (rl.columns = childrenColumns);
          } else {
            if(dataPower!==undefined&&dataPower.length>0){
              const attr=dataPower.filter((dataItem)=>dataItem.id==rl.id);
              rl.readonly = attr[0].isEdit==true?false:true;
              rl.disabled = attr[0].isEdit==true?false:true;
              rl.isShow = attr[0].isDisabled;
              rl.required =attr[0].isMustInput;
              rl.rules = [];
            }
            else{
              rl.readonly = true;
              rl.disabled = true;
              rl.required =true;
              rl.rules = [];
            }
            
            return rl;
          }
        });
        row.list = colRowList;
        return row;
      });
      return (item.columns = colRows);
    } else {
      if(dataPower!==undefined&&dataPower.length>0){
        const attr=dataPower.filter((dataItem)=>dataItem.id==item.id);
        item.readonly = attr[0].isEdit==true?false:true;
        item.disabled = attr[0].isEdit==true?false:true;
        item.isShow = attr[0].isDisabled;
        item.required =attr[0].isMustInput;
        item.rules = [];
      }
      else{
        item.readonly = true;
        item.disabled = true;
        item.required =true;
        item.rules = [];
      }
      return item;
    }
  });
  return newRefList;
}
//获取当前节点后面的所有节点
export function getSubsequentNodes(element, elementRegistry) {
  const visited = new Set();
  const subsequentNodes = [];
  const queue = [];

  // 初始节点入队
  queue.push(element.businessObject);

  while (queue.length > 0) {
    const currentElement = queue.shift();

    // 获取当前元素的所有流出连线
    const outgoingFlows = currentElement.outgoing || [];

    outgoingFlows.forEach(flow => {
      const targetElement = flow.targetRef;

      // 检查是否是有效流程节点且未访问过
      if (targetElement && 
          targetElement.$type !== 'bpmn:SequenceFlow' && 
          !visited.has(targetElement.id)) {
            if(targetElement.$type !== 'bpmn:ExclusiveGateway' &&
              targetElement.$type !== 'bpmn:InclusiveGateway' && 
              targetElement.$type !== 'bpmn:EndEvent'){
                visited.add(targetElement.id);
                subsequentNodes.push(targetElement);
              }
            // 将目标元素的业务对象入队继续处理
              queue.push(targetElement);
        }
    });
  }

  // 转换为显示元素
  return subsequentNodes.map(node => 
    elementRegistry.get(node.id)
  );
}
/**
 * 根据网关ID获取后续节点及方向条件
 * @param {string} gatewayId 网关的ID
 * @param {Modeler} modeler bpmn-js模型实例
 * @returns {Array} 后续节点数组
 */
export function getNextNodes(gatewayId,gateRunType, modeler) {
  const elementRegistry = modeler.get('elementRegistry');
  const gateway = elementRegistry.get(gatewayId);

  const connectionStore=connectionAttr();

  if (!gateway) {
    console.error('未找到网关元素');
    return [];
  }

  if (!isGateway(gateway)) {
    console.error('该元素不是网关类型');
    return [];
  }

  const outgoingFlows = gateway.businessObject.outgoing || [];
  const nextNodes = [];
  const formKeys=[];

  outgoingFlows.forEach(flow => {
    //获取条件中设置的表单字段列表
    const collection = connectionStore.connections.find(
      item => item.connectionNo===flow.id
    );
    if(collection){
      const expressBody=collection.expressBody;
      for(let i=0;i<expressBody.length;i++){
        const children=expressBody[i].children;
        for(let j=0;j<children.length;j++){
          const obj=children[j].conditions;
          for(let k=0;k<obj.length;k++){
            const businessSelected=obj[k].businessSelected;
            if(['workflowInstance','variable'].includes(businessSelected[0])==false){
              if(!formKeys.includes(businessSelected[1]))
              formKeys.push(businessSelected[1]);
            }
          }
        }
      }
    }

    const targetRef = flow.targetRef;
    if (targetRef&&gateRunType==="1") {
      const targetElement = elementRegistry.get(targetRef.id);
      if (targetElement) {
        const nodeInfo={
          id:targetElement.businessObject.id,
          name:targetElement.businessObject.name
        }
        nextNodes.push(nodeInfo);
      }
    }
  });

  const flow={
    nodeList:nextNodes,
    formKeys:formKeys
  }

  return flow;
}

/**
 * 判断元素是否为网关
 * @param {Object} element 元素对象
 * @returns {boolean}
 */
function isGateway(element) {
  const gatewayTypes = [
    'bpmn:ExclusiveGateway',
    'bpmn:ParallelGateway',
    'bpmn:InclusiveGateway',
    'bpmn:EventBasedGateway',
    'bpmn:ComplexGateway'
  ];
  return gatewayTypes.includes(element.type);
}
/**
 * 
 * @param elementId 获取上一步信息
 * @param visited 
 * @returns 
 */
export function getIncomingTree(elementId: string, visited: Set<string> = new Set()): FlowElementTree {
  const modeler = modelerStore();
  const elementRegistry = modeler.getModeler?.get('elementRegistry');
  const currentElement = elementRegistry.get(elementId) as Element;

  console.log(currentElement,"currentElement3333333333")
  if (!currentElement || visited.has(elementId)) {
    return null;
  }

  visited.add(elementId);

  const incomingFlows = currentElement.businessObject.incoming || [];
  const incomingElements: FlowElementTree[] = [];

  for (const flow of incomingFlows) {
    const sourceElement = elementRegistry.get(flow.sourceRef.id);
    if (sourceElement) {
      incomingElements.push({
        id: sourceElement.id,
        type: sourceElement.type,
        name: sourceElement.businessObject.name,
        incoming: getIncomingTree(sourceElement.id, visited)?.incoming || [],
        outgoing: sourceElement.outgoing.length>0?sourceElement.outgoing:[]
      });
    }
  }

  return {
    id: currentElement.id,
    type: currentElement.type,
    name: currentElement.businessObject.name,
    incoming: incomingElements
  };
}
export const generateRandomChar=()=> {
  const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
  const randomIndex = Math.floor(Math.random() * characters.length);
  return characters[randomIndex];
};
export const generateRandomString=()=> {
  let result = '';
  for (let i = 0; i < 6; i++) {
    result += generateRandomChar();
  }
  return result;
};
// 获取开始事件节点
export function getStartTask(elementRegistry) {
  const startEvents = elementRegistry.filter(element => 
    is(element, 'bpmn:StartEvent')
  );
  if (!startEvents.length) return null;

  const startEvent = startEvents[0];
 
  return startEvent;
}

// 递归查找用户任务
export function findNextUserTask(element, elementRegistry) {
  // 获取所有出站序列流
  const outgoing = element.outgoing || [];
  let userTasks=[];
  
  for (const sequenceFlow of outgoing) {

    // 获取目标元素
    const target = elementRegistry.get(sequenceFlow.id);
    
    if (!target) continue;
    
    // 如果是用户任务，直接返回
    if (is(target, 'bpmn:UserTask')||
        is(target, 'bpmn:EndEvent')) {
      userTasks.push(target);
      continue;
    }
    //如果是线
    else if(is(target, 'bpmn:SequenceFlow')){
      const flowTarget=target.target;
      if (is(flowTarget, 'bpmn:UserTask')||
          is(target, 'bpmn:EndEvent')) {
        userTasks.push(flowTarget);
        continue;
      }
      else{
        const result = findNextUserTask(flowTarget, elementRegistry);
      if (result) return result;
      }
    }
    // 如果是网关，递归检查所有分支
    else if (is(target, 'bpmn:ExclusiveGateway') || 
             is(target, 'bpmn:ParallelGateway') ||
             is(target, 'bpmn:InclusiveGateway')) {
      const result = findNextUserTask(target, elementRegistry);
      if (result) return result;
    }
    // 其他元素继续递归
    else {
      const result = findNextUserTask(target, elementRegistry);
      if (result) return result;
    }
  }
  
  return userTasks;
}
//数组筛选
export function filterArrayByArray<T extends Record<string, any>>(
  sourceArray: T[],
  filterArray: T[],
  key: keyof T
): T[] {
  // 从筛选条件数组中提取所有匹配值
  const filterValues = filterArray.map(item => item[key]);
  
  // 使用 Array.filter 方法筛选源数组
  return sourceArray.filter(item => filterValues.includes(item[key]));
}

